/**
 * @Author:       lee
 * @DateTime:     2017-11-04 12:30:34
 * @Description:  对象
 */
/**
 *  对象属性初始值的简写
 */
function createPerson(name,age) {
  return {
    name:name,
    age:age
  }
}
var funlee = createPerson('funlee',25)
console.log(funlee)
//ES6--属性初始值的简写
//消除属性名称与局部变量之间的重复书写
function createPerson(name,age) {
  return {
    name,
    age
  }
}
var p = createPerson('lee',20)
console.log(p)
//---------------------------------------------------------------------------------
/**
 *  对象方法的简写
 */
let person = {
  say:() => {
    console.log('hello!!')
  }
}
person.say()
//ES6简写形式
let person = {
  say(){
    console.log('我被简写了')
  }
}
person.say()
//---------------------------------------------------------------------------------
/**
 *  可计算属性名
 *  任何可用于对象实例括号记法的属性名，也可以作为字面量中的计算属性名
 */
var person = {}
var lastName = 'funlee'
person['first name'] = 'Nicholas'
person[lastName] = 'Zakas'

console.log(person['first name'])
console.log(person[lastName])
console.log(person['funlee'])
console.log(person[lastName] == person.funlee) //true

let suffix = ' name'
let person = {
  ['first ' + suffix]:'Nickols',
  ['last ' + suffix]:'Zakas'
}

console.log(person['first name'])
console.log(person['last name'])
//---------------------------------------------------------------------------------
/**
 *  Object.is() 其运行结果在大部分情况中与 === 运算符相同
 *  唯一的区别是在于+0和-0被识别为不相等冰球NaN与NaN等价
 *  
 */
console.log(+0 == -0)//true
console.log(+0 === -0)//true
console.log(Object.is(+0,-0))//false

console.log(+NaN == -NaN)//false
console.log(+NaN === -NaN)//false
console.log(Object.is(+NaN,-NaN))//false

console.log(5 == '5')//true
console.log(5 === '5')//false
console.log(Object.is(5,'5'))//false
//---------------------------------------------------------------------------------
/**
 *  Object.assign() 
 *  可以接收任意数量的源对象
 *  后面的覆盖前面的
 */
//mixin -- "浅复制?????/"
function mixin(receiver,supplier) {
  Object.keys(supplier).forEach(function(key) {
    receiver[key] = supplier[key]
  })
  return receiver;
}

var obj1 = {
  name:'obj1',
  age:20
}
var obj2 = {}
mixin(obj2,obj1)
console.log(obj2)

var receiver = {}
Object.assign(receiver,
  {
    type:'js',
    name:'file.js'
  },
  {
    type:'css'
  }
)
console.log(receiver.type)//css
//---------------------------------------------------------------------------------
/**
 *  枚举顺序
 *  没怎么用过
 */
var obj = {
  a:1,
  0:1,
  c:1,
  2:1,
  b:1,
  1:1
}
obj.d = 1
console.log(Object.getOwnPropertyNames(obj))//["0", "1", "2", "a", "c", "b", "d"]
//---------------------------------------------------------------------------------
/**
 *  改变对象原型
 *  ES5缺少对象在实例化后改变原型的标准方法
 */
let person = {
  getGreeting() {
    return 'Hello'
  }
}
let dog = {
  getGreeting() {
    return 'woof'
  }
}
//以person为原型
let friend = Object.create(person)
console.log(friend.getGreeting()) //hello
console.log(Object.getPrototypeOf(friend) === person) //true

//更改为以dog为原型
Object.setPrototypeOf(friend,dog)
console.log(friend.getGreeting()) //woof
console.log(Object.getPrototypeOf(friend) === dog) //true
//---------------------------------------------------------------------------------
/**
 *  super
 *  既想重写对象实例的方法
 *  又需要调用与它同名的原型方法
 *  但，必须要在使用简写方法的对象中使用Super引用
 */
let person = {
  getGreeting() {
    return 'Hello'
  },
  test() {
    return 'this is a test'
  }
}
let dog = {
  getGreeting() {
    return 'woof'
  }
}

let friend = {
  getGreeting() {
    return Object.getPrototypeOf(this).getGreeting.call(this) + ',Hi!'
  }
}

//将原型设置为person
Object.setPrototypeOf(friend,person)
console.log(friend.test())
console.log(friend.getGreeting())  //Hello,Hi!
console.log(Object.getPrototypeOf(friend) === person) //true

//将原型设置为dog
console.log(friend.getGreeting()) //Hello ,woof
console.log(Object.getPrototypeOf(friend) === dog) //true

//利用super改写
let person = {
  getGreeting() {
    return 'Hello'
  },
  sayName() {
    return 'person'
  }
}
let dog = {
  getGreeting() {
    return 'woof'
  }
}

let friend = {
  getGreeting() {
    return super.getGreeting() + ',hi!'
  },
  sayName:function() {
    return super.sayName()
  }
}
Object.setPrototypeOf(friend,person)
console.log(Object.getPrototypeOf(friend) === person) //true

console.log(friend.getGreeting())  //Hello,Hi!
console.log(friend.sayName())  //错误
//---------------------------------------------------------------------------------
/**
 *  super引用在多重继承下的使用
 */

let person = {
  getGreeting() {
    return 'Hello'
  }
}
//以person对象为原型
let friend = {
  getGreeting() {
    return Object.getPrototypeOf(this).getGreeting.call(this) + ',Hi!'
  }
}
Object.setPrototypeOf(friend,person)

//原型是friend
let relative = Object.create(friend)

console.log(person.getGreeting())//hello
console.log(friend.getGreeting())//hello hi
console.log(relative.getGreeting())//error:Uncaught RangeError: Maximum call stack size exceeded  栈溢出

//super解决上述问题

let person = {
  getGreeting() {
    return 'Hello'
  }
}
//以person对象为原型
let friend = {
  getGreeting() {
    return super.getGreeting() + ',Hi!'
  }
}
Object.setPrototypeOf(friend,person)

//原型是friend
let relative = Object.create(friend)

console.log(person.getGreeting())//hello
console.log(friend.getGreeting())//hello hi
console.log(relative.getGreeting())//hello hi 
